package cn.iocoder.yudao.module.security.config;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.ssl.SSLContextBuilder;
import org.elasticsearch.client.RestClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.net.ssl.SSLContext;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;

@Configuration
public class EsConfig {

    @Value("${elasticsearch.host}")
    private String esHost;

    @Value("${elasticsearch.username}")
    private String username;

    @Value("${elasticsearch.password}")
    private String password;

    @Value("${elasticsearch.certificate}")
    private String certificate;

    @Bean
    public ElasticsearchClient elasticsearchClient() throws Exception {

        Path caCertPath = Paths.get(certificate); // 从ES服务器获取证书
        /*KeyStore trustStore = KeyStore.getInstance("jks");
        try (InputStream is = Files.newInputStream(caCertPath.toFile().toPath())) {
            trustStore.load(is, password.toCharArray());
        }*/
        CertificateFactory factory = CertificateFactory.getInstance("X.509");
        Certificate ca = factory.generateCertificate(Files.newInputStream(caCertPath));

        // 2. 创建信任库‌:ml-citation{ref="2" data="citationList"}
        KeyStore trustStore = KeyStore.getInstance("PKCS12");
        trustStore.load(null, null);
        trustStore.setCertificateEntry("es-ca", ca);

        // 3. 配置SSL上下文
        SSLContext sslContext = SSLContextBuilder.create()
                .loadTrustMaterial(trustStore, null)
                .build();
        /*SSLContext sslContext = SSLContextBuilder
                .create()
                .loadTrustMaterial(trustStore, null)
                .build();
        SSLContext sslContext = SSLContextBuilder
                .create()
                //.loadTrustMaterial(caCertPath.toFile())
                .loadTrustMaterial(caCertPath.toFile(), "elasticsearch".toCharArray())
                .build();*/

        // 1. 加载CA证书

        // 2. 创建认证凭证
        BasicCredentialsProvider creds = new BasicCredentialsProvider();
        creds.setCredentials(
                AuthScope.ANY,
                new UsernamePasswordCredentials(username, password)
        );

        // 3. 构建RestClient
        RestClient restClient = RestClient.builder(HttpHost.create(esHost))
                .setHttpClientConfigCallback(hc -> hc
                        .setSSLContext(sslContext)
                        .setDefaultCredentialsProvider(creds))
                .build();

        // 4. 创建Java API客户端
        ElasticsearchTransport transport = new RestClientTransport(
                restClient, new JacksonJsonpMapper());

        return new ElasticsearchClient(transport);
    }

    public static void main(String[] args) {
        EsConfig esConfig = new EsConfig();
        try {
            esConfig.esHost = "https://59.153.165.44:9200";
            esConfig.username = "elastic";
            esConfig.password = "lw0D2MO7+sh20IcxEwcT";
            esConfig.certificate = "E:\\pfsense\\winlogbeat-8.17.1-windows-x86_64\\http.p12";
            ElasticsearchClient client = esConfig.elasticsearchClient();
            System.out.println(client);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

